(** Efficient replacement for ntuples in Ocaml *)

module type Serialized_type =
sig
    type serialized
end

module type Serialized_dbm =
sig
    type t
    type serialized
    val opendbm : string -> Dbm.open_flag list -> int -> t
    val close : t -> unit
    val find : t -> string -> serialized
    val add : t -> string -> serialized -> unit
    val replace : t -> string -> serialized -> unit
    val remove : t -> string -> unit
    val firstkey : t -> string
    val nextkey : t -> string
    val iter : (string -> serialized -> 'a) -> t -> unit
end

module Make (Type: Serialized_type)
        : (Serialized_dbm with type serialized = Type.serialized) =
struct
    include Dbm
    type serialized = Type.serialized
    let serialize (x: serialized) : string = Marshal.to_string x []
    let deserialize (x: string) : serialized = Marshal.from_string x 0
    let find db key = deserialize (find db key)
    let add db key value = add db key (serialize value)
    let replace db key value = replace db key (serialize value)
    let iter f db = iter (fun key value -> f key (deserialize value)) db
end

(* Usage:
 * module DetDBM = Ocaml_dbm.Make(struct type value = det end)
 * let db = DetDBM.opendbm "data.db" [Dbm.Dbm_rdonly] 0o644
 * let value : det = .......
 * DetDBM.add db (string_of_int k) value
*)
